package com.ctshk.rpc.booking.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ctshk.common.dto.Result;
import com.ctshk.common.enums.IsDeletedCode;
import com.ctshk.common.enums.SystemError;
import com.ctshk.common.exception.BusinessException;
import com.ctshk.common.model.PageResponse;
import com.ctshk.common.utils.EntityUtil;
import com.ctshk.common.utils.SnowflakeIdWorker;
import com.ctshk.rpc.booking.dto.unsubscribe.get.SupplierUnsubscribeDetailsGetDTO;
import com.ctshk.rpc.booking.dto.unsubscribe.get.SupplierUnsubscribeFileGetDTO;
import com.ctshk.rpc.booking.dto.unsubscribe.get.SupplierUnsubscribeGetDTO;
import com.ctshk.rpc.booking.dto.unsubscribe.page.SupplierReconciliationBookingDTO;
import com.ctshk.rpc.booking.dto.unsubscribe.page.SupplierUnsubscribePageDTO;
import com.ctshk.rpc.booking.entity.SupplierOrder;
import com.ctshk.rpc.booking.entity.SupplierUnsubscribe;
import com.ctshk.rpc.booking.entity.SupplierUnsubscribeDetails;
import com.ctshk.rpc.booking.entity.SupplierUnsubscribeFile;
import com.ctshk.rpc.booking.enums.SupplierGroupNumberEnum;
import com.ctshk.rpc.booking.enums.SupplierVerifyStatusEnum;
import com.ctshk.rpc.booking.mapper.SupplierOrderMapper;
import com.ctshk.rpc.booking.mapper.SupplierUnsubscribeDetailsMapper;
import com.ctshk.rpc.booking.mapper.SupplierUnsubscribeFileMapper;
import com.ctshk.rpc.booking.mapper.SupplierUnsubscribeMapper;
import com.ctshk.rpc.booking.req.unsubscribe.page.SupplierUnsubscribeFinanceContactsPageReq;
import com.ctshk.rpc.booking.req.unsubscribe.page.SupplierUnsubscribePageReq;
import com.ctshk.rpc.booking.req.unsubscribe.save.SupplierUnsubscribeDetailsSaveReq;
import com.ctshk.rpc.booking.req.unsubscribe.save.SupplierUnsubscribeFileSaveReq;
import com.ctshk.rpc.booking.req.unsubscribe.save.SupplierUnsubscribeSaveReq;
import com.ctshk.rpc.booking.service.ISupplierUnsubscribeService;
import com.ctshk.rpc.finance.req.supplier.SupplierReconciliationAmountDTO;
import com.ctshk.rpc.finance.service.IFinanceSupplierReconciliationService;
import com.ctshk.rpc.system.dto.MainDataCurrencyQueryDTO;
import com.ctshk.rpc.system.dto.UserDTO;
import com.ctshk.rpc.system.req.MainDataCurrencyUpdateStatusReq;
import com.ctshk.rpc.system.service.IMainDataCurrencyService;
import com.ctshk.rpc.system.service.ISysUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 * 供应商退订 服务实现类
 * </p>
 *
 * @author 谢诗宏
 * @since 2021-03-25
 */
@Slf4j
@DubboService
public class SupplierUnsubscribeServiceImpl implements ISupplierUnsubscribeService {
    @Autowired
    SupplierUnsubscribeMapper supplierUnsubscribeMapper;
    @Autowired
    SupplierUnsubscribeDetailsMapper supplierUnsubscribeDetailsMapper;
    @Autowired
    SupplierUnsubscribeFileMapper supplierUnsubscribeFileMapper;
    @Autowired
    SupplierOrderMapper supplierOrderMapper;
    @DubboReference
    IMainDataCurrencyService mainDataCurrencyService;
    @DubboReference
    ISysUserService sysUserService;
    @DubboReference
    private IFinanceSupplierReconciliationService financeSupplierReconciliationService;

    @Override
    public PageResponse<SupplierUnsubscribePageDTO> getFinanceContactsPage(SupplierUnsubscribeFinanceContactsPageReq unsubscribeFinanceContactsPageReq) {
        Page<SupplierUnsubscribe> supplierUnsubscribePage = new Page<>(unsubscribeFinanceContactsPageReq.getPageNo(), unsubscribeFinanceContactsPageReq.getPageSize());
        QueryWrapper<SupplierUnsubscribe> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().le(unsubscribeFinanceContactsPageReq.getSupplierId() != null, SupplierUnsubscribe::getSupplierId, unsubscribeFinanceContactsPageReq.getSupplierId());
        queryWrapper.lambda().eq(unsubscribeFinanceContactsPageReq.getReserveTypeId() != null, SupplierUnsubscribe::getReserveTypeId, unsubscribeFinanceContactsPageReq.getReserveTypeId());
        queryWrapper.lambda().eq(unsubscribeFinanceContactsPageReq.getCurrencyId() != null, SupplierUnsubscribe::getCurrencyId, unsubscribeFinanceContactsPageReq.getCurrencyId());
        queryWrapper.lambda().like(StringUtils.isNotBlank(unsubscribeFinanceContactsPageReq.getProductNumber()), SupplierUnsubscribe::getProductNumber, unsubscribeFinanceContactsPageReq.getProductNumber());
        queryWrapper.lambda().like(StringUtils.isNotBlank(unsubscribeFinanceContactsPageReq.getCancellationNumber()), SupplierUnsubscribe::getCancellationNumber, unsubscribeFinanceContactsPageReq.getCancellationNumber());
        queryWrapper.lambda().ge(unsubscribeFinanceContactsPageReq.getFromGmtCreate() != null, SupplierUnsubscribe::getGmtCreate, unsubscribeFinanceContactsPageReq.getFromGmtCreate());
        queryWrapper.lambda().le(unsubscribeFinanceContactsPageReq.getToGmtCreate() != null, SupplierUnsubscribe::getGmtCreate, unsubscribeFinanceContactsPageReq.getToGmtCreate());
        queryWrapper.lambda().ge(unsubscribeFinanceContactsPageReq.getCreateId() != null, SupplierUnsubscribe::getCreateId, unsubscribeFinanceContactsPageReq.getCreateId());
        queryWrapper.lambda().eq(SupplierUnsubscribe::getIsDeleted, IsDeletedCode.NO.getCode());
        queryWrapper.lambda().orderByDesc(SupplierUnsubscribe::getGmtCreate);
        Page<SupplierUnsubscribe> iPage = supplierUnsubscribeMapper.selectPage(supplierUnsubscribePage, queryWrapper);
        List<SupplierUnsubscribe> records = iPage.getRecords();
        if (CollectionUtils.isEmpty(records)) {
            return new PageResponse<>(new ArrayList<>(), iPage.getCurrent() == 1, iPage.getTotal() <= (iPage.getCurrent() * iPage.getSize()), iPage.getTotal(), iPage.getCurrent(), iPage.getSize());
        }
        List<SupplierUnsubscribePageDTO> supplierUnsubscribePageDTOList = EntityUtil.copyList(records, SupplierUnsubscribePageDTO.class);
        return new PageResponse<>(supplierUnsubscribePageDTOList, iPage.getCurrent() == 1, iPage.getTotal() <= (iPage.getCurrent() * iPage.getSize()), iPage.getTotal(), iPage.getCurrent(), iPage.getSize());
    }

    @Override
    public PageResponse<SupplierUnsubscribePageDTO> getUnsubscribeList(SupplierUnsubscribePageReq supplierUnsubscribePageReq) {
        Page<SupplierUnsubscribe> supplierUnsubscribePage = new Page<>(supplierUnsubscribePageReq.getPageNo(), supplierUnsubscribePageReq.getPageSize());
        QueryWrapper<SupplierUnsubscribe> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().like(StringUtils.isNotBlank(supplierUnsubscribePageReq.getCancellationNumber()), SupplierUnsubscribe::getCancellationNumber, supplierUnsubscribePageReq.getCancellationNumber());
        queryWrapper.lambda().like(StringUtils.isNotBlank(supplierUnsubscribePageReq.getSupplierOrderNumber()), SupplierUnsubscribe::getSupplierOrderNumber, supplierUnsubscribePageReq.getSupplierOrderNumber());
        queryWrapper.lambda().ge(supplierUnsubscribePageReq.getFromGmtCreate() != null, SupplierUnsubscribe::getGmtCreate, supplierUnsubscribePageReq.getFromGmtCreate());
        queryWrapper.lambda().le(supplierUnsubscribePageReq.getToGmtCreate() != null, SupplierUnsubscribe::getGmtCreate, supplierUnsubscribePageReq.getToGmtCreate());
        queryWrapper.lambda().ge(supplierUnsubscribePageReq.getCreateId() != null, SupplierUnsubscribe::getCreateId, supplierUnsubscribePageReq.getCreateId());
        queryWrapper.lambda().le(supplierUnsubscribePageReq.getSupplierId() != null, SupplierUnsubscribe::getSupplierId, supplierUnsubscribePageReq.getSupplierId());
        queryWrapper.lambda().eq(supplierUnsubscribePageReq.getReserveTypeId() != null, SupplierUnsubscribe::getReserveTypeId, supplierUnsubscribePageReq.getReserveTypeId());
        queryWrapper.lambda().eq(supplierUnsubscribePageReq.getVerifyStatus() != null, SupplierUnsubscribe::getVerifyStatus, supplierUnsubscribePageReq.getVerifyStatus());
        if (supplierUnsubscribePageReq.getIsUseGroupNumber() != null) {
            if (supplierUnsubscribePageReq.getIsUseGroupNumber() == SupplierGroupNumberEnum.YES.getCode()) {
                queryWrapper.lambda().isNotNull(SupplierUnsubscribe::getGroupNumber);
            } else if (supplierUnsubscribePageReq.getIsUseGroupNumber() == SupplierGroupNumberEnum.NO.getCode()) {
                queryWrapper.lambda().isNull(SupplierUnsubscribe::getGroupNumber);
            }
        }
        queryWrapper.lambda().eq(SupplierUnsubscribe::getIsDeleted, IsDeletedCode.NO.getCode());
        queryWrapper.lambda().orderByDesc(SupplierUnsubscribe::getGmtCreate);
        Page<SupplierUnsubscribe> iPage = supplierUnsubscribeMapper.selectPage(supplierUnsubscribePage, queryWrapper);
        List<SupplierUnsubscribe> records = iPage.getRecords();
        if (CollectionUtils.isEmpty(records)) {
            return new PageResponse<>(new ArrayList<>(), iPage.getCurrent() == 1, iPage.getTotal() <= (iPage.getCurrent() * iPage.getSize()), iPage.getTotal(), iPage.getCurrent(), iPage.getSize());
        }
        List<SupplierUnsubscribePageDTO> supplierUnsubscribePageDTOList = EntityUtil.copyList(records, SupplierUnsubscribePageDTO.class);

        Set<Long> userIds = supplierUnsubscribePageDTOList.stream().map(SupplierUnsubscribePageDTO::getCreateId).collect(Collectors.toSet());
        List<UserDTO> userDTOS = sysUserService.queryCacheUsers(userIds);
        if (CollectionUtils.isNotEmpty(userDTOS)) {
            supplierUnsubscribePageDTOList.forEach(supplier -> {
                for (UserDTO userDTO : userDTOS) {
                    supplier.setCreate(userDTO.getCreateDept());
                    break;
                }
            });
        }
        return new PageResponse<>(supplierUnsubscribePageDTOList, iPage.getCurrent() == 1, iPage.getTotal() <= (iPage.getCurrent() * iPage.getSize()), iPage.getTotal(), iPage.getCurrent(), iPage.getSize());
    }

    @Override
    public Result<Long> saveUnsubscribe(SupplierUnsubscribeSaveReq supplierUnsubscribeSaveReq, Long userId) {
        log.info("【供应商退订-保存退订】方法入参:{}", JSON.toJSONString(supplierUnsubscribeSaveReq));
        if (supplierUnsubscribeSaveReq.getId() != null) {
            SupplierUnsubscribe supplierUnsubscribe = supplierUnsubscribeMapper.selectById(supplierUnsubscribeSaveReq.getId());
            if (supplierUnsubscribe.getVerifyStatus() != SupplierVerifyStatusEnum.UNREADY_VERIFY.getCode()) {
                //退订单是未对账状态的，才允许编辑
                throw new BusinessException(SystemError.SUPPLIER_BOOKING_UNSUBSCRIBE_13901);
            }
        }
//        SupplierOrder supplierOrder = supplierOrderMapper.selectById(supplierUnsubscribeSaveReq.getSupplierOrderId());
        LocalDateTime nowDateTime = LocalDateTime.now();
        SupplierUnsubscribe supplierUnsubscribe = EntityUtil.copy(supplierUnsubscribeSaveReq, SupplierUnsubscribe.class);

        BigDecimal total = BigDecimal.ZERO;
        for (SupplierUnsubscribeDetailsSaveReq detailReq : supplierUnsubscribeSaveReq.getSupplierUnsubscribeDetailsSaveReqList()) {
            BigDecimal subtotal = detailReq.getPrice().multiply(new BigDecimal(detailReq.getNumber()));
            total = total.add(subtotal);
        }
        if (total.compareTo(BigDecimal.ZERO) == -1) {
            //总计金额必须大于等于0
            throw new BusinessException(SystemError.SUPPLIER_BOOKING_UNSUBSCRIBE_13901);
        }
        MainDataCurrencyQueryDTO exchangeRate = getExchangeRateByName(supplierUnsubscribeSaveReq.getCurrencyId());
        BigDecimal plannedExchangeRate = exchangeRate.getPlannedExchangeRate();//计划汇率
        BigDecimal refundAmount = total.multiply(plannedExchangeRate);//退订金额

        supplierUnsubscribe.setExchangeRate(plannedExchangeRate);
        supplierUnsubscribe.setRefundAmount(refundAmount);
        supplierUnsubscribe.setModifiedId(userId);
        supplierUnsubscribe.setGmtModified(nowDateTime);
        if (supplierUnsubscribe.getId() == null) {
            supplierUnsubscribe.setId(SnowflakeIdWorker.nextId());
            supplierUnsubscribe.setCreateId(userId);
            supplierUnsubscribe.setGmtCreate(nowDateTime);
            supplierUnsubscribe.setIsDeleted(IsDeletedCode.NO.getCode());
            supplierUnsubscribe.setCancellationNumber(generatorUnsubscribeNumber(nowDateTime));
            supplierUnsubscribe.setVerifyStatus(SupplierVerifyStatusEnum.UNREADY_VERIFY.getCode());
            supplierUnsubscribeMapper.insert(supplierUnsubscribe);
        } else {
            supplierUnsubscribeMapper.updateById(supplierUnsubscribe);
            // 先清除子表数据，后新增
            supplierUnsubscribeDetailsMapper.delete(new QueryWrapper<SupplierUnsubscribeDetails>().lambda()
                    .eq(SupplierUnsubscribeDetails::getSupplierUnsubscribeId, supplierUnsubscribe.getId()));
            supplierUnsubscribeFileMapper.delete(new QueryWrapper<SupplierUnsubscribeFile>().lambda()
                    .eq(SupplierUnsubscribeFile::getSupplierUnsubscribeId, supplierUnsubscribe.getId()));
        }
        // save detail
        List<SupplierUnsubscribeDetails> supplierUnsubscribeDetails = EntityUtil.copyList(supplierUnsubscribeSaveReq.getSupplierUnsubscribeDetailsSaveReqList(), SupplierUnsubscribeDetails.class);
        supplierUnsubscribeDetails.forEach(supplierUnsubscribeDetail -> {
            supplierUnsubscribeDetail.setId(SnowflakeIdWorker.nextId());
            supplierUnsubscribeDetail.setSupplierUnsubscribeId(supplierUnsubscribe.getId());
            supplierUnsubscribeDetail.setCreateId(userId);
            supplierUnsubscribeDetail.setGmtCreate(nowDateTime);
            supplierUnsubscribeDetail.setModifiedId(userId);
            supplierUnsubscribeDetail.setGmtModified(nowDateTime);
            supplierUnsubscribeDetail.setIsDeleted(IsDeletedCode.NO.getCode());
        });
        supplierUnsubscribeDetailsMapper.insertBatchSomeColumn(supplierUnsubscribeDetails);
        // save file
        List<SupplierUnsubscribeFileSaveReq> supplierUnsubscribeFileSaveReqList = supplierUnsubscribeSaveReq.getSupplierUnsubscribeFileSaveReqList();
        if (CollectionUtils.isNotEmpty(supplierUnsubscribeFileSaveReqList)) {
            List<SupplierUnsubscribeFile> supplierUnsubscribeFiles = EntityUtil.copyList(supplierUnsubscribeFileSaveReqList, SupplierUnsubscribeFile.class);
            supplierUnsubscribeFiles.forEach(supplierUnsubscribeFile -> {
                supplierUnsubscribeFile.setId(SnowflakeIdWorker.nextId());
                supplierUnsubscribeFile.setSupplierUnsubscribeId(supplierUnsubscribe.getId());
            });
            supplierUnsubscribeFileMapper.insertBatchSomeColumn(supplierUnsubscribeFiles);
        }
        return Result.success(supplierUnsubscribe.getId());
    }

    /**
     * 退訂單號,編號規則：TDD+年後2位+月日4位+時分秒6位+4位随机数字
     *
     * @param nowDateTime
     * @return
     */
    private String generatorUnsubscribeNumber(LocalDateTime nowDateTime) {
        String yearCode = String.valueOf(nowDateTime.getYear()).substring(2, 4);
        String monthCode = StringUtils.leftPad(String.valueOf(nowDateTime.getMonthValue()), 2, "0");
        String dayCode = StringUtils.leftPad(String.valueOf(nowDateTime.getDayOfMonth()), 2, "0");
        String randomNumber = String.valueOf((int) ((Math.random() * 9 + 1) * 1000));
        StringBuilder orderNumberSb = new StringBuilder();
        orderNumberSb.append("TDD").append(yearCode).append(monthCode).append(dayCode).append(randomNumber);
        return orderNumberSb.toString();
    }

    /**
     * 根据币种ID获取汇率，获取汇率,
     *
     * @return
     */
    private MainDataCurrencyQueryDTO getExchangeRateByName(Long currencyId) {
        MainDataCurrencyUpdateStatusReq mainDataCurrencyUpdateStatusReq = new MainDataCurrencyUpdateStatusReq();
        mainDataCurrencyUpdateStatusReq.setId(currencyId);
        Result<MainDataCurrencyQueryDTO> queryCurrencyRateResult = mainDataCurrencyService.query(mainDataCurrencyUpdateStatusReq);
        if (!queryCurrencyRateResult.isSuccess()) {
            SystemError defined = SystemError.getDefined(queryCurrencyRateResult.getCode());
            throw new BusinessException(defined);
        }
        return queryCurrencyRateResult.getData();
    }

    @Override
    public SupplierUnsubscribeGetDTO getUnsubscribe(Long id) {
        SupplierUnsubscribe supplierUnsubscribe = supplierUnsubscribeMapper.selectById(id);
        if (supplierUnsubscribe == null) {
            //供应商退订记录不存在
            throw new BusinessException(SystemError.SUPPLIER_BOOKING_UNSUBSCRIBE_13903);
        }
        SupplierUnsubscribeGetDTO supplierUnsubscribeGetDTO = EntityUtil.copy(supplierUnsubscribe, SupplierUnsubscribeGetDTO.class);
        // detail
        QueryWrapper<SupplierUnsubscribeDetails> detailQueryWrapper = new QueryWrapper<>();
        detailQueryWrapper.lambda().eq(SupplierUnsubscribeDetails::getSupplierUnsubscribeId, id);
        detailQueryWrapper.lambda().eq(SupplierUnsubscribeDetails::getIsDeleted, IsDeletedCode.NO.getCode());
        List<SupplierUnsubscribeDetails> supplierUnsubscribeDetails = supplierUnsubscribeDetailsMapper.selectList(detailQueryWrapper);
        List<SupplierUnsubscribeDetailsGetDTO> supplierUnsubscribeDetailsGetDTOS = EntityUtil.copyList(supplierUnsubscribeDetails, SupplierUnsubscribeDetailsGetDTO.class);
        supplierUnsubscribeGetDTO.setSupplierUnsubscribeDetailsGetDTOList(supplierUnsubscribeDetailsGetDTOS);
        // file
        QueryWrapper<SupplierUnsubscribeFile> fileQueryWrapper = new QueryWrapper<>();
        fileQueryWrapper.lambda().eq(SupplierUnsubscribeFile::getSupplierUnsubscribeId, id);
        List<SupplierUnsubscribeFile> supplierUnsubscribeFiles = supplierUnsubscribeFileMapper.selectList(fileQueryWrapper);
        List<SupplierUnsubscribeFileGetDTO> supplierUnsubscribeFileGetDTOS = EntityUtil.copyList(supplierUnsubscribeFiles, SupplierUnsubscribeFileGetDTO.class);
        supplierUnsubscribeGetDTO.setSupplierUnsubscribeFileGetDTOList(supplierUnsubscribeFileGetDTOS);
        // booking order info
        SupplierOrder supplierOrder = supplierOrderMapper.selectOne(new QueryWrapper<SupplierOrder>().lambda()
                .eq(SupplierOrder::getId, supplierUnsubscribe.getSupplierOrderId())
                .eq(SupplierOrder::getIsDeleted, IsDeletedCode.NO.getCode()));
        SupplierReconciliationBookingDTO supplierReconciliationBookingDTO = EntityUtil.copy(supplierOrder, SupplierReconciliationBookingDTO.class);
        supplierUnsubscribeGetDTO.setSupplierReconciliationBookingDTO(supplierReconciliationBookingDTO);

        Result<List<SupplierReconciliationAmountDTO>> byOrderIdList = null;
        try {
            UserDTO userDTO = sysUserService.queryCacheUser(supplierReconciliationBookingDTO.getCreateId());
            if (null != userDTO) {
                supplierReconciliationBookingDTO.setCreate(userDTO.getCreateDept());
            }
            byOrderIdList = financeSupplierReconciliationService.getByOrderIdList(Arrays.asList(supplierUnsubscribe.getSupplierOrderId()));
        } catch (Exception e) {
            log.error("【供应商退订-查询退订信息】查询财务异常,error:{}", e.getMessage(), e);
        }
        if (null == byOrderIdList || !byOrderIdList.isSuccess()) {
            log.error("【供应商退订-查询退订信息】查询财务异常");
        } else if (CollectionUtils.isNotEmpty(byOrderIdList.getData())) {
            SupplierReconciliationAmountDTO supplierReconciliationAmountDTO = byOrderIdList.getData().get(0);
            supplierReconciliationBookingDTO.setPayStatus(supplierReconciliationAmountDTO.getPayStatus());
            supplierReconciliationBookingDTO.setPayableAmount(supplierReconciliationAmountDTO.getPayableAmount());
            supplierReconciliationBookingDTO.setPaidAmount(supplierReconciliationAmountDTO.getPaidAmount());
            supplierReconciliationBookingDTO.setUnPayAmount(supplierReconciliationAmountDTO.getUnPayAmount());
        }
        return supplierUnsubscribeGetDTO;
    }
}
